package cn.zxd.pub;




import cn.zxd.util.*;

import java.sql.*;

/**
 * ResultSet包裹类
 * 完成类似4GL的游标的FETCH功能,主要用于大数据量的问题.
 * @author Yang Yalin
 * @version 1.0
 */
public class RSWrapper {

    // @Field
    private Connection con;
    private DBOper db;
    /**
     * flag = true: 传入Connection
     * flag = false: 不传入Connection
     **/
    private boolean useOutterConnection = false;

    public CErrors mErrors = new CErrors(); // 错误信息

    /**
     * 为批量操作而准备的语句和游标对象
     */
    private ResultSet mResultSet = null;
    private Statement mStatement = null;

    private SchemaSet container = null;

    private boolean isClosed = false;

    /** 用于不定长sql查询返回字段个数 */
    private int colNum = 0;

    /** 用于集团交叉销售的提数Txt */
    private String mEncode;

    // @Constructor
    public RSWrapper(Connection tConnection) {
        con = tConnection;
        useOutterConnection = true;
    }

    public RSWrapper() {
        con = null;
        useOutterConnection = false;
    }


    /**
     * 准备数据查询条件
     * @param strSQL String
     * @return boolean
     */
    public boolean prepareData(SchemaSet container, String strSQL) {
        this.container = container;
        isClosed = false;

        System.out.println("prepareData:" + strSQL);

        if (mResultSet != null) {
            // @@错误处理
            CError tError = new CError();
            tError.moduleName = "LMDutyDB";
            tError.functionName = "prepareData";
            tError.errorMessage = "数据集非空，程序在准备数据集之后，没有关闭！";
            this.mErrors.addOneError(tError);
            return false;
        }

        if (!useOutterConnection) {
            con = DBConnPool.getConnection();
        }
        try {
            mStatement = con.createStatement(ResultSet.TYPE_FORWARD_ONLY,
                    ResultSet.CONCUR_READ_ONLY);
            mResultSet = mStatement.executeQuery(StrTool.GBKToUnicode(strSQL));
            if (mResultSet != null) {
                colNum = mResultSet.getMetaData().getColumnCount();
                System.out.println("in...try....mResultSet is not null ");
            }
        } catch (Exception e) {
            e.printStackTrace();
            // @@错误处理
            CError tError = new CError();
            tError.moduleName = "RSWrapper";
            tError.functionName = "prepareData";
            tError.errorMessage = e.toString();
            this.mErrors.addOneError(tError);
            try {
                mResultSet.close();
            } catch (Exception ex2) {}
            try {
                mStatement.close();
            } catch (Exception ex3) {}
            if (!useOutterConnection) {
                try {
                    con.close();
                } catch (Exception et) {}
            }
            return false;
        }

        System.out.println("success prepared...");
        return true;
    }

    /**
     * 获取数据集
     * @return boolean
     */
    private boolean next() {
        boolean flag = true;
        if (null == mResultSet) {
            CError tError = new CError();
            tError.moduleName = "LMDutyDB";
            tError.functionName = "hasMoreData";
            tError.errorMessage = "数据集为空，请先准备数据集！";
            this.mErrors.addOneError(tError);
            return false;
        }
        try {
            flag = mResultSet.next();
        } catch (Exception ex) {
            CError tError = new CError();
            tError.moduleName = "LMDutyDB";
            tError.functionName = "hasMoreData";
            tError.errorMessage = ex.toString();
            this.mErrors.addOneError(tError);
            try {
                mResultSet.close();
                mResultSet = null;
            } catch (Exception ex2) {}
            try {
                mStatement.close();
                mStatement = null;
            } catch (Exception ex3) {}
            if (!useOutterConnection) {
                try {
                    con.close();
                } catch (Exception et) {}
            }
            return false;
        }
        return flag;
    }

    /**
     * 获取定量数据
     * @return SchemaSet
     */
    public SchemaSet getData() {
        container.clear();

        if (null == mResultSet) {
            CError tError = new CError();
            tError.moduleName = "RSWrapper";
            tError.functionName = "getData";
            tError.errorMessage = "数据集为空，请先准备数据集！";
            this.mErrors.addOneError(tError);
            return null;
        }

        if(isClosed)
        {
            return container;
        }

        try {
            int tCount = 0;
            String clzName = container.getClass().getName();
            clzName = clzName.substring(clzName.lastIndexOf(".") + 1,
                    clzName.length() - 3) + "Schema";

            //注意mResultSet.next()的作用
            if (mResultSet != null) {
                while (tCount++ < 1000 ) {
                    if(!mResultSet.next())
                    {
                        isClosed = true;
                        break;
                    }
                    else
                    {
                        Schema schema = (Schema) Class.forName(
                                "com.bull.iss.schema." + clzName).newInstance();
                        schema.setSchema(mResultSet, 1);
                        container.add(schema);
                    }
                }
            }
            System.out.println("RSWrapper Actual Fetched Row:" + tCount);
        } catch (Exception ex) {
            ex.printStackTrace();
            CError tError = new CError();
            tError.moduleName = "RSWrapper";
            tError.functionName = "getData";
            tError.errorMessage = ex.toString();
            this.mErrors.addOneError(tError);
            try {
                mResultSet.close();
                mResultSet = null;
            } catch (Exception ex2) {}
            try {
                mStatement.close();
                mStatement = null;
            } catch (Exception ex3) {}
            if (!useOutterConnection) {
                try {
                    con.close();
                } catch (Exception et) {}
            }
            return null;
        }
        return container;
    }

    /**
     * 获取定量数据
     *
     * @return SchemaSet
     */
    public SSRS getSSRS() {

        mEncode = null;
        SSRS ssrs = new SSRS(this.colNum);
        if (null == mResultSet) {
            CError tError = new CError();
            tError.moduleName = "RSWrapper";
            tError.functionName = "getData";
            tError.errorMessage = "数据集为空，请先准备数据集！";
            this.mErrors.addOneError(tError);
            return null;
        }

        if (isClosed) {
            return ssrs;
        }
        StringBuffer strReturn = new StringBuffer();

        try {
            int tCount = 0;

            // 注意mResultSet.next()的作用
            if (mResultSet != null) {
                long a = System.currentTimeMillis();
                ResultSetMetaData meta = mResultSet.getMetaData();
                long b = System.currentTimeMillis();
//				if ((b - a) > 0)
//					System.out.println("WR0：" + (b - a));
                while (tCount++ < 200) {
                    if (!mResultSet.next()) {
                        isClosed = true;
                        break;
                    } else {
                        for (int i = 1; i <= colNum; i++) {
                            a = System.currentTimeMillis();
                            String str = getDataValue(meta, mResultSet, i);
                            b = System.currentTimeMillis();
//							if ((b - a) > 0)
//								System.out.println("WR1：" + (b - a));

                            a = System.currentTimeMillis();
                            ssrs.SetText(str);
                            b = System.currentTimeMillis();
//							if ((b - a) > 0)
//							System.out.println("WR2："+(b-a) );

                            /** 集团交叉销售所使用的 */
                            if (i != colNum)
                            {
                                a = System.currentTimeMillis();
//		                        strReturn = strReturn + str + SysConst.PACKAGESPILTER;
                                strReturn.append(str);
                                strReturn.append(SysConst.PACKAGESPILTER);
                                b = System.currentTimeMillis();
//		                        if ((b - a) > 0)
//									System.out.println("WR3：" + (b - a));
                            }
                            else
                            {
                                a = System.currentTimeMillis();
//		                        strReturn = strReturn + str;
                                strReturn.append(str);
                                b = System.currentTimeMillis();
//		                        if ((b - a) > 0)
//									System.out.println("WR3：" + (b - a));
                            }
                        }
                        a = System.currentTimeMillis();
                        strReturn.append(SysConst.RECORDSPLITER);
                        b = System.currentTimeMillis();
//						if ((b - a) > 0)
//							System.out.println("WR4：" + (b - a));
                    }
                }
                String strTemp = "0" + SysConst.PACKAGESPILTER
                        + String.valueOf(tCount - 1) + SysConst.RECORDSPLITER;
                a = System.currentTimeMillis();
                StringBuffer stringBuffer = new StringBuffer();
                stringBuffer.append(strTemp);
                stringBuffer.append(strReturn);
                mEncode = stringBuffer.toString();
                b = System.currentTimeMillis();
//				if ((b - a) > 0)
//					System.out.println("WR5：" + (b - a));
            }
            System.out.println("RSWrapper Actual Fetched Row:" + tCount);
        } catch (Exception ex) {
            ex.printStackTrace();
            CError tError = new CError();
            tError.moduleName = "RSWrapper";
            tError.functionName = "getData";
            tError.errorMessage = ex.toString();
            this.mErrors.addOneError(tError);
            try {
                mResultSet.close();
                mResultSet = null;
            } catch (Exception ex2) {
            }
            try {
                mStatement.close();
                mStatement = null;
            } catch (Exception ex3) {
            }
            if (!useOutterConnection) {
                try {
                    con.close();
                } catch (Exception et) {
                }
            }
            return null;
        }
        return ssrs;
    }

    /**
     * 获取定量数据
     *
     * @return SchemaSet
     */
    public String encode() {
        return mEncode;
    }
    /**
     * 把ResultSet中取出的数据转换为相应的数据值字符串
     * 输出：如果成功执行，返回True，否则返回False，并且在Error中设置错误的详细信息
     *
     * @param rsmd
     *            ResultSetMetaData
     * @param rs
     *            ResultSet
     * @param i
     *            int
     * @return String
     */
    public String getDataValue(ResultSetMetaData rsmd, ResultSet rs, int i) {
        String strValue = "";

        try {
            int dataType = rsmd.getColumnType(i);
            int dataScale = rsmd.getScale(i);
            int dataPrecision = rsmd.getPrecision(i);
            // 数据类型为字符
            if ((dataType == Types.CHAR) || (dataType == Types.VARCHAR)) {
                // 由于存入数据库的数据是GBK模式，因此没有必要做一次unicodeToGBK
                // strValue = StrTool.unicodeToGBK(rs.getString(i));
                strValue = rs.getString(i);
            }
            // 数据类型为日期、时间
            else if ((dataType == Types.TIMESTAMP) || (dataType == Types.DATE)) {
                FDate fDate = new FDate();
                strValue = fDate .getString(rs.getDate(i));
            }
            // 数据类型为浮点
            else if ((dataType == Types.DECIMAL) || (dataType == Types.FLOAT)
                    || (dataType == Types.DOUBLE)) {
                // strValue = String.valueOf(rs.getFloat(i));
                // 采用下面的方法使得数据输出的时候不会产生科学计数法样式
                strValue = String.valueOf(rs.getBigDecimal(i));
                // 去零处理
                strValue = PubFun.getInt(strValue);
            }
            // 数据类型为整型
            else if ((dataType == Types.INTEGER)
                    || (dataType == Types.SMALLINT)) {
                strValue = String.valueOf(rs.getInt(i));
                strValue = PubFun.getInt(strValue);
            }
            // 数据类型为浮点
            else if (dataType == Types.NUMERIC) {
                if (dataScale == 0) {
                    if (dataPrecision == 0) {
                        // strValue = String.valueOf(rs.getDouble(i));
                        // 采用下面的方法使得数据输出的时候不会产生科学计数法样式
                        strValue = String.valueOf(rs.getBigDecimal(i));
                    } else {
                        strValue = String.valueOf(rs.getLong(i));
                    }
                } else {
                    // strValue = String.valueOf(rs.getDouble(i));
                    // 采用下面的方法使得数据输出的时候不会产生科学计数法样式
                    strValue = String.valueOf(rs.getBigDecimal(i));
                }
                strValue = PubFun.getInt(strValue);
            }

        } catch (SQLException ex) {
            ex.printStackTrace();
        }

        return StrTool.cTrim(strValue);
    }
    /**
     * 关闭数据集
     * @return boolean
     */
    public boolean close() {
        boolean flag = true;
        try {
            if (null == mResultSet) {
                CError tError = new CError();
                tError.moduleName = "RSWrapper";
                tError.functionName = "closeData";
                tError.errorMessage = "数据集已经关闭了！";
                this.mErrors.addOneError(tError);
                flag = false;
            } else {
                mResultSet.close();
                mResultSet = null;
            }
        } catch (Exception ex2) {
            CError tError = new CError();
            tError.moduleName = "RSWrapper";
            tError.functionName = "closeData";
            tError.errorMessage = ex2.toString();
            this.mErrors.addOneError(tError);
            flag = false;
        }
        try {
            if (null == mStatement) {
                CError tError = new CError();
                tError.moduleName = "RSWrapper";
                tError.functionName = "closeData";
                tError.errorMessage = "语句已经关闭了！";
                this.mErrors.addOneError(tError);
                flag = false;
            } else {
                mStatement.close();
                mStatement = null;
            }
        } catch (Exception ex3) {
            CError tError = new CError();
            tError.moduleName = "RSWrapper";
            tError.functionName = "closeData";
            tError.errorMessage = ex3.toString();
            this.mErrors.addOneError(tError);
            flag = false;
        }

        System.out.println("use out connection:" + useOutterConnection);

        if (!useOutterConnection) {
            try {
                con.close();
                System.out.println("inner connection closed");
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        return flag;
    }


    public static void main(String[] args) {
//        RSWrapper rswrapper = new RSWrapper();
//        LMRiskSet lmRiskSet = new LMRiskSet();
//        rswrapper.prepareData(lmRiskSet, "select * from lmrisk");
//        do {
//            rswrapper.getData();
//            System.out.println("get data count:" + lmRiskSet.size());
//        } while (lmRiskSet.size() > 0);
//        rswrapper.close();
//        System.out.println("commplete");

    }
}
